<template>
  <transition name="q-transition--scale">
    <q-card v-if="initShow" v-show="pageVisible" key="email-button" ref="QxPageRef"
            class="qx-page overflow-hidden no-outline q-pt-md q-px-md" tabIndex="1" @keyup.esc.stop="closePage">
      <q-bar v-if="headerBar" class="qx-page-header text-grey-8 bg-transparent">
        <span class="text-h6 text-weight-medium">{{ attrs.header || $t('Title') }}</span>
        <q-space />
        <q-btn v-if="attrs.closeBtn !== false" :dense="isDense" class="q-btn-tip" icon="reply_all" v-bind="btnBind"
               @click="closePage">
          <q-tooltip v-bind="$tooltipAttr">{{ $t('GoBack') }}</q-tooltip>
        </q-btn>
      </q-bar>

      <div v-if="fullHeight" :class="attrs.classes" :style="{ height: setMaxHeight() }">
        <slot :maxHeight="maxHeight" name="default"></slot>
      </div>
      <div v-else-if="nonScrollArea" :class="attrs.classes" :style="{ maxHeight: setMaxHeight() }">
        <slot :maxHeight="maxHeight" name="default"></slot>
      </div>
      <q-scroll-area v-else ref="ScrollArea" :style="AreaStyle" :visible="false">
        <div :class="attrs.classes" class="q-pb-xs">
          <slot name="default"></slot>
          <q-resize-observer debounce="0" @resize="onResize" />
        </div>
      </q-scroll-area>

      <template v-if="menuBtn">
        <div :class="footerCls" class="qx-page-footer row q-pt-sm q-mb-sm q-gutter-x-md rounded-borders">
          <slot :done="done" :scope="menuBind" :startLoading="startLoading" name="menuLeft"></slot>
          <q-btn v-if="attrs.submitBtn !== false" color="primary" icon="published_with_changes" unelevated
                 v-bind="menuBind" @click="onConfirm">
            {{ attrs.submitText || $t('Confirm') }}
          </q-btn>
          <q-btn v-if="attrs.closeBtn !== false" icon="cancel_schedule_send" outline text-color="primary"
                 v-bind="menuBind" @click="closePage">
            {{ attrs.closeText || $t('Close') }}
          </q-btn>
          <slot name="menuRight"></slot>
        </div>
      </template>

      <q-inner-loading :showing="loading">
        <q-spinner-ios color="primary" size="3rem" />
      </q-inner-loading>
    </q-card>
  </transition>
</template>

<script setup>
import { dom } from 'quasar'
import { computed, inject, nextTick, ref, useAttrs, watch } from 'vue'

const props = defineProps({
  fullHeight: Boolean,
  nonScrollArea: Boolean,
  menuBtn: { type: Boolean, default: true },
  headerBar: { type: Boolean, default: true }
})

const attrs = useAttrs()
const emits = defineEmits(['confirm'])
const isDense = inject('isDense', true)

const AreaStyle = ref({})
const QxPageRef = ref(null)
const initShow = ref(false)
const maxHeight = ref('100%')
const btnBind = { 'fab-mini': true, round: true, flat: true }
const loading = defineModel('loading', { type: Boolean, default: false })
const pageVisible = defineModel('modelValue', { type: Boolean, default: false })
const menuBind = ref({ 'no-wrap': true, padding: '.4rem 1rem', loading: loading.value })

const footerCls = computed(() => {
  const { btnAlign } = attrs
  if (btnAlign === 'left') return 'justify-start'
  if (btnAlign === 'right') return 'justify-end'
  return 'justify-center'
})

const setMaxHeight = () => {
  const { headerBar, menuBtn } = props
  let tempPX = 0
  if (headerBar) tempPX += 3
  if (!menuBtn) {
    maxHeight.value = `calc(100% - ${tempPX}rem)`
    return maxHeight.value
  }
  const node = QxPageRef.value.$el.querySelector('.qx-page-footer')
  maxHeight.value = `calc(100% - ${tempPX}rem - ${node ? dom.height(node) : 0}px)`
  return maxHeight.value
}

const onResize = size => {
  if (!pageVisible.value) return
  AreaStyle.value.height = `${size.height}px`
  AreaStyle.value.maxHeight = setMaxHeight()
}
const initData = () => {
  if (!pageVisible.value) return
  if (!initShow.value) initShow.value = true
  nextTick(() => QxPageRef.value && QxPageRef.value.$el.focus())
}

watch(pageVisible, () => initData())
const done = isClose => {
  loading.value = false
  if (isClose === false) return
  closePage()
}
const startLoading = () => loading.value = true
const onConfirm = () => {
  startLoading()
  emits('confirm', done)
}
const closePage = e => {
  e.cancelBubble = true
  const parentNode = e.srcElement?.previousElementSibling?.parentElement?.parentElement
  parentNode && parentNode.focus()
  const beforeClose = attrs.onBeforeClose || attrs.beforeClose
  if (beforeClose && typeof beforeClose === 'function') beforeClose()
  else pageVisible.value = false
}
</script>